home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Utilities Professional 1-1500
/
Utilities Professional 1-1500 (1994)(WPD)[!].iso
/
12511500
/
var1459.dms
/
var1459.adf
/
Fonts
/
Fonts.doc
< prev
next >
Wrap
Text File
|
1992-05-02
|
48KB
|
1,368 lines
2 FONTS
2.1 INTRODUCTION
In the previous chapters when we have printed text with help
of the low level Text() function or the high level IntuiText
structure, we have always used a font called "Topaz". The
reason why we always have used this font is simply because it
is the Amiga's default font and exist in ROM.
Topaz is, however, not the only font available on the Amiga.
There exist thousands more, but these are not placed in ROM,
they are loaded from disks. Loading fonts from disks is luckily
quite a simple task since all necessary functions have already
been written and exist in the "Diskfont Library".
In this chapter I will show you how to open the Diskfont
Library, and use its functions. This involves finding out
which fonts are available, loading them into memory and
how to use them. I will also explain how to create your own
fonts and use them in your own programs.
2.2 FONTS
A font is a collection of graphical objects that represents
characters. Since the Amiga was built as a graphical work
station the system has been designed to handle all different
types of fonts with great efficiency. Fonts of almost any size
can be used, and the Amiga can itself convert fonts to styles
like italic, underlined, bold, extended, and all possible
All fonts have a "Baseline" on which the characters are placed.
Characters like "abcdef" will all be on and above the baseline.
On the other hand, characters like "gjpqy" will also use some
space under the baseline.
Here are three letters - 'a' 'b' and 'g'. As you can see will
the 'g' use same space below the baseline. (The baseline is
like normal rows on a paper.)
#
#
#### #
# #
# #
# #
##### ##### #####
# # # # # #
# # # # # #
# # # # # #
# # # # # #
###### ##### ##### <= Baseline
#
#
# #
####
2.3 ROM FONTS
As said above, there exist for the moment only one ROM based
font on the Amiga. It is Topaz and exist in two sizes, 8 and
9 pixels high. (ROM is like the normal memory in a computer,
but when the computer is turned off the contents will still be
intact. The disadvantage is that you can not change anything
which is stored in ROM. ROM - "Read Only Memory".)
Topaz two sizes:
- 9 pixels high (32 characters/row low resolution)
(64 - " - high resolution)
- 8 pixels high (40 - " - low resolution)
(80 - " - high resolution)
Note! The limit on how many characters/row you can print simply
depends on the width of the screen. In the above example I
assume that low resolution means a 320 pixels wide display,
and high resolution 640 pixels wide screen. Nowadays you can
not be sure what the maximum width is simply because many
users are now working on displays with overscan, extra large
screens, see previous chapter for more information. I my
self is currently using a 736 pixels wide and 540 lines tall
display.
2.3.1 TEXTATTR STRUCTURE
When you want to use a font you allocate a TextAttr structure
(defined in the header file "graphics/text.h"). In the
structure you write your requirements, the name of the font,
height, style (normal, underlined, bold, italic...) and what
type it is (if the font exist in ROM or on Disk).
The TextAttr structure look like this:
struct TextAttr
{
STRPTR ta_Name;
UWORD ta_YSize;
UBYTE ta_Style;
UBYTE ta_Flags;
};
ta_Name: Name of the font together with the extension ".font".
For example: To get the font Topaz you should write
"topaz.font".
ta_YSize: The Height of the font. To get a 9 pixel high font
simply write 9.
ta_Style: There exist five different styles that may be
combined. The styles are: Normal, Underlined, Bold
Italic and Extended. You specify which styles you
want to use with the following flags: FS_NORMAL,
FSF_UNDERLINED, FSF_BOLD, FSF_ITALIC and
FSF_EXTENDED.
To get a combination (e.g. Bold and Italic) use the
binary OR operator "|" (e.g. FSF_BOLD | FSF_ITALIC).
Note! If you ask for an underlined font for example,
it is not sure there exist one. You should then get
the font you want in the normal style, and then
change it with help of the SetSoftStyle() function.
(Explained later in this chapter.)
ta_Flags: This field tells the Amiga what type of font you
want. If it is a ROM based font write FPF_ROMFONT.
If it is a disk based font write FPF_DISKFONT.
(See below for a complete Flag list.)
If you want to use the ROM font Topaz, 9 pixels high, normal
style, you should initialize the TextAttr structure like this:
struct TextAttr my_font_attr=
{
"topaz.font", /* Name of the font. */
9, /* Height (in pixels) */
FS_NORMAL, /* Style */
FPF_ROMFONT /* Exist in ROM. */
};
2.3.2 OPEN ROM FONTS
After you have initialized the TextAttr structure you call the
OpenFont() function to get access to a ROM font. The Amiga will
open the font which closes matches your requirements in the
TaxtAttr structure. If OpenFont() finds the font it returns a
pointer to a TextFont structure and tells the system that you
are using the font.
Synopsis: font = OpenFont( attr );
font: (struct TextFont *) Pointer to a TextFont structure
which is declared in header file "graphics/text.h".
See below for more information about this structure.
If OpenFont() could not find the font it returns
NULL.
attr: (struct TextAttr *) Pointer to an already initialized
TextAttr structure. OpenFont() will try to open the
font which closes matches your requirements.
2.3.3 CLOSE ROM FONTS
All fonts you have opened must be "closed" before your program
terminates! Since the font is in ROM no memory would be wasted
if you forgot to close a previously opened font, but your
program code would not look very good, so be careful. Close
a font by calling the CloseFont() function.
Synopsis: CloseFont( font );
font: (struct TextFont *) Pointer to a previously opened
TextFont structure. Note that you should NOT try to
close a font which you have not opened!
2.4 DISK FONTS
Most fonts does not exist in ROM but are loaded from disks.
The greatest advantage of loading fonts rather than including
the fonts with the program itself is that several programs
running at the same time can all use the same set of fonts.
A lot of memory is therefore saved.
2.4.1 DISKFONT LIBRARY
Most of the special routines which are involved with loading
and using disk fonts are automatically taken care of by the
Diskfont Library. Whenever you want to use disk fonts you
should remember to open this library.
The diskfont library is opened as all other libraries with an
OpenLibrary() call, and closed by and CloseLibrary() call. If
the diskfont library not have already been opened by some
other program it will be loaded from the system disk. (From
the logical device "LIBS:", named "diskfont.library".
Here is an example:
struct Library *DiskfontBase;
DiskfontBase = (struct DiskfontBase *)
OpenLibrary( "diskfont.library", 0 );
if( !DiskfontBase )
clean_up( "Could not open Diskfont library!" );
...
if( DiskfontBase )
CloseLibrary( DiskfontBase );
2.4.2 FINDING OUT WHICH FONTS ARE AVAILABLE
After you have opened the diskfont library you can use the
special function AvailFonts() which will scan through the
font directory of the system disk, and return a complete list
of available fonts.
Synopsis: missing = AvailFonts( buffer, size, type );
missing: (long) If the buffer was not big enough to store the
complete list of fonts in the extra number of bytes
needed is returned. If 0 is returned the buffer was
big enough for a complete list of fonts.
buffer: (char *) Pointer to some memory were the list of
fonts can be stored.
size: (long) The size of the buffer (in bytes).
type: (long) If you want to look for available fonts which
are already in the memory set the flag "AFF_MEMORY".
If you want to search the disk for available fonts,
set the flag "AFF_DISK". To search both the memory
and the disk set both flags with the binary OR
operator between ("AFF_DISK | AFF_MEMORY").
The font list consists of a AvailFontsHeader structure followed
by a list of AvailFonts structures (both declared in header
file "libraries/diskfont.h"):
struct AvailFontsHeader
{
UWORD afh_NumEntries;
};
afh_NumEntries: Number of AvailFonts structures.
struct AvailFonts
{
UWORD af_Type;
struct TextAttr af_Attr;
};
af_Type: If the font exist in memory the "AFF_MEMORY" flag is
set. If the font exist on the disk the "AFF_DISK" flag
is set.
af_Attr: An initialized TextAttr structure. This structure can
be examined to find the font's name, size, style etc...
(See above for more information about the TextAttr
structure.)
It is impossible to know how big memory buffer you need for the
AvailFonts() function. You can of course allocate a very big
buffer and be quite sure it will be big enough, but this is not
a good solution. A lot of memory is wasted if the buffer is too
big, and it may happen that the buffer still is too small. The
solution to this problem is to call the AvailFonts() function
with the buffer size set to 0. AvailFonts() will then return
the number of bytes needed to store the complete list. Allocate
a buffer with this size, and call the AvailFonts() function
once again, but this time give it the new buffer.
Here is an example:
int size;
struct AvailFontsHeader *avail_fonts_header;
struct AvailFonts *avail_fonts;
/* Find out which fonts are available both in the memory */
/* as well on the disk. The buffer size is set to 0, hence */
/* the function will return the correct number of bytes */
/* needed to store the complete list in: */
size = AvailFonts( NULL, 0, AFF_DISK | AFF_MEMORY );
/* Allocate the buffer: (Now we know what size is needed.) */
avail_fonts_header = (struct AvailFontsHeadr *)
AllocMem( size, MEMF_CLEAR );
/* Call the function AvailFonts() again, but this time we give */
/* it a buffer to store the information in: (Remember to still */
/* check that the buffer was big enough! Some other task could */
/* have changed something in the FONTS: device while we */
/* allocated the buffer. Never trust the Amiga...) */
if( AvailFonts( avail_fonts_header, size, AFF_DISK | AFF_MEMORY ) )
clean_up( "Buffer to small to store the font list in!" );
/* We can now examine the list. See example 5. */
When the Amiga tries to load a font it looks in the logical
device "FONTS:". If you have more fonts on another disk you
can reassign the logical device "FONTS:" with help of the
AmigaDOS command "Assign". If you have a collection of nice
fonts in the drawer "MyFonts" on the disk in "df1:" you
call Assign like this: "Assign FONTS: df1:MyFonts" (without
quotations)
2.4.3 OPEN DISK FONTS
You "open" a disk font by initializing a TextAttr structure
with your requirements and call the OpenDiskFont() function.
Remember that the diskfont library must have been opened before
you may use this or the AvailFonts() function. If the font have
not already been loaded into the memory by some other program
it will automatically be done.
Synopsis: font = OpenDiskFont( attr );
font: (struct TextFont *) Pointer to a TextFont structure
which is declared in header file "graphics/text.h".
See below for more information about this structure.
attr: (struct TextAttr *) Pointer to an already initialized
TextAttr structure. OpenDiskFont() will try to open
the font which closes matches your requirements.
2.4.4 CLOSE DISK FONTS
All fonts you have opened must be closed before your program
terminates. A lot of memory is otherwise wasted. Please be very
careful with this! You close a font with the CloseFont()
function as described above. Both ROM and Disk fonts are closed
with this function.
Synopsis: CloseFont( font );
font: (struct TextFont *) Pointer to a previously opened
TextFont structure. Note that you should NOT try to
close a font which you have not opened!
2.5 USE THE NEW FONTS
Once you have successfully opened the desired fonts you may
start to use them. As described in the beginning of this
chapter you can either use the low level functions Move() and
Text() or the high level IntuiText structures.
2.5.1 HIGH LEVEL
The high level approach is a clean and nice way to print text.
For short messages it can be a bit tedious since you need to
use some structures just to print some text. These structures
that can feel a bit complicated and unnecessary are extremely
useful and easy to handle if a lot of text is needed. The
advantage with these structures is that they can easily be
combined with each other as well as with other objects like
gadgets, requesters, etc...
Here is what you have to do:
1. Initialize a TextAttr structure with your requirements
as described above.
2. Open the desired font as have also been described above.
3. Initialize the IntuiText structures as normal (see
chapter 3 Graphics) but set the ITextFont pointer to the
desired TextAttr structure.
4. Either connect the IntuiTedxt structure to an object
(gadget, requester etc...) or print it directly with help
of the PrintIText() function.
Here is an example: ("my_window" is a pointer to an already
opened window.)
/* Pointer to the diskfont library: */
struct Library *DiskfontBase;
/* The attributes for our desired font: */
struct TextAttr my_font_attr=
{
"Courier.font", /* Name of the font. */
18, /* Height, 18 pixels tall. */
FS_NORMAL, /* Style, normal. */
FPF_DISKFONT /* Load it from the disk. */
};
/* Intuition's text structure: */
struct IntuiText my_intui_text=
{
1, /* FrontPen, colour register 1. */
2, /* BackPen, colour register 2. */
JAM2, /* DrawMode, draw the characters with colour 1, */
/* on a colour 2 background. */
10, 20, /* LeftEdge, TopEdge. Position of the text. */
&my_font_attr, /* ITextFont, use the Courier font. */
"Hello", /* IText, the text that will be printed. */
NULL, /* NextText, last structure in the list. */
};
/* Open the Intuition Library, windows etc... */
/* Open the DiskFont library: */
DiskfontBase = (struct DiskfontBase *)
OpenLibrary( "diskfont.library", 0 );
if( !DiskfontBase )
clean_up( "Could not open Diskfont library!" );
/* Open the desired font: */
font = OpenDiskFont( &my_font_attr );
/* Tell Intuition to print the text: */
PrintIText( my_window->RPort, &my_intui_text, 0, 0 );
/* Close the DiskFont Library: */
if( DiskfontBase )
CloseLibrary( DiskfontBase );
/* Close the window, Intuition Library etc... */
2.5.2 LOW LEVEL
When it is very little text that should be printed, or you do
not want to mess around with structures you can use the low
level functions Move() and Text(). Before you can use these
functions you have to (of course) open the font as normal, but
also tell the RastPort to use the new font. Use the SetFont()
function to change a RastPort's default font.
Synopsis: error = SetFont( rp, font );
error: (long) If OK 0 is returned, else an error number is
returned which means something went wrong.
rp: (struct RastPort *) Pointer to the RastPort that
should be affected.
font: (struct TextFont *) Pointer to a TextFont structure
which has previously been "opened".
The the first character of the text will be printed at the
Rastport's (cp_x, cp_y) coordinate. (The current cp_x and cp_y
values can be found in the Rastport structure. see chapter 12
LOWLEVELGRAPHICS for more information about Rastports).
To change the printing position use the function Move()
with a pointer to the Rastport that should be affected and
the new coordinate as parameters.
Synopsis: Move( rast_port, x, y );
rast_port: (struct RastPort *) Pointer to the Rastport that
should be affected.
x: (long) The new X position.
y: (long) The new Y position.
When a character is printed the base line will be placed at the
current cp_x, cp_y coordinate. The point below which is marked
with a star (*) is the coordinate for the first character.
00000000000000000000000
00000000010000000000000
00000000010000000000000
00111100010000000000000
00000010010000000000000
00000010010000000000000
00000010010000000000000
00111110011111000111110
01000010010000101000010
01000010010000101000010
01000010010000101000010
01000010010000101000010
*0111111011111000111110 <= Base line
00000000000000000000010
00000000000000000000010
00000000000000001000010
00000000000000000111100
00000000000000000000000
If the base line is 13 lines below the top of the character, you
must set the Y coordinate to 13 or higher, or the top part of
the characters will not fit.
2.2.2 PRINT TEXT
To print text on the Amiga you can use the low level Text()
function which supports fonts of all sizes and all styles
(more about this later).
To print text you need a pointer to the Rastport which should
be affected, a pointer to a text string and finally a value
that tells Text() how many characters of the string should be
printed. Only one line each call may be printed, and no
formatting, word-wrapping etc is done. The Rastports current
font will be used.
Synopsis: Text( rast_port, string, nr_of_chr );
rast_port: (struct RastPort *) Pointer to the RastPort that
should be affected.
string: (char *) Pointer to a text string that will be
printed.
nr_of_chr: (long) The number of characters that should be
printed.
Here is an example that prints "Hello" on the display:
Text( &my_rast_port, "HELLO", 5 );
The high level IntuiText structure also supports different
types of fonts. See chapter 3 Graphics for more information
about this structure and how to use it.
2.6 STYLES
When you set your requirements in the TextAttr structure you
can among many things specify what style (bold, underlined,
italic, extended or a combination) you want the font to be in.
If you are luck the font with your specified style exist. If
not you can let the Amiga change the font into desired style
by calling the SetSoftStyle() function.
Before you use the SetSoftStyle() function you should call the
AskSoftStyle() function to check if you are allowed to change
the font as desired. The routines for changing the font style
may not work very good with some fonts, and you are therefore
sometimes advised not to change the style.
For the moment there exist five different styles you may use.
The header file "graphics/text.h" has defined them as:
FS_NORMAL Normal style.
FSF_EXTENDED Extra wide characters.
FSF_ITALIC Italic (characters leaning to the right).
FSF_BOLD Extra thick characters.
FSF_UNDERLINED Underlined characters.
To produce a combination of the styles you simply put the
binary operator OR (|) between the flags.
Note that you should always first try to load the font with the
desired style. It is only when the desired style does not exist
you should try to modify it with the SetSoftStyle() function.
Synopsis: a_style = AskSoftStyle( rast_port )
a_style: (UWORD) The function returns a bit field where the
allowed style bits for the checked font are set. This
value should be used as a parameter when you call
the SetSoftStyle() function.
rast_port: (struct RastPort *) Pointer to the rastport to which
the font you want to check is connected.
Once you know which styles you may use you can change the font
by calling the SetSoftStyle() function.
Synopsis: new_style = SetSoftStyle( rast_port, style, a_style );
new_style: (UWORD) The function will only create the styles it
is allowed to do (see a_styles), and it may therefore
happen that the function will not generate all of the
styles you wanted. This returned value tells us which
style bits it used.
rast_port: (struct RastPort *) Pointer to the rastport to which
the font you want to change is connected.
style: (UWORD) The desired style.
a_style: (UWORD) The styles you may use. This value was
returned by AskSoftStyle(). If you want to be able
to use all styles and do not care if some styles
would look strange set this field to 0xFFFF (all
styles allowed). This can result in some very ugly
styles, and is therefore not recommended.
Here is an example:
UWORD style; /* Desired style. */
UWORD a_style; /* Styles allowed. */
UWORD new_style; /* Style we got. */
/* Set the desired style: (A combination of underlined, */
/* bold and italic.) */
style = FSF_UNDERLINED | FSF_BOLD | FSF_ITALIC;
/* Check which styles we may use: */
a_style = AskSoftStyle( my_window->RPort );
/* Change the window's font style: */
new_style = SetSoftStyle( my_window->RPort, style, a_style );
/* Tell the user what style we will use: */
printf( "Style:" );
if( new_style )
printf( "%s%s%s!\n",
new_style & FSF_UNDERLINED ? " Underlined" : "",
new_style & FSF_BOLD ? " Bold" : "",
new_style & FSF_ITALIC ? " Italic" : "" );
else
printf( " normal!" );
printf( "!\n" );
2.7 CREATING YOUR OWN FONTS
If you want to create a new font yourself you should use the
font editor program ("fed") which is included on the "Extras"
disk you received when you bought your Amiga. To create your
own fonts without this types of utility is very complicated.
However, if you want to create a very small font set with a
very limited number of characters it is possible to do it. I
will here explain how to do this since it is rather interesting
and good to know how a font set is actually constructed.
If you want to include a font set together with your program
code you do actually not need to do very much. I have written
a small utility called PrintFont (in drawer "Include Font")
which will load a specified font and print all information
about it in C code. This code can then simply be included in
your own program code.
A font consists of:
1. A TextFont structure to which all other information of
the font is connected to.
2. A memory area where the graphics of the font's characters
are declared. (Character data)
3. A list of data which tells us where each character's
fontdata begins and how wide each character is.
4. If it is a proportional font (each character has it's own
width, for example an "i" is not as wide as a "W") we
need information about how much space is needed between
each character when printed. (Character Space). All
proportional fonts does not need this array. If it does
not exist the nominal width (tf_XSpace) will be used.
5. Finally, if the font is proportional we also need
information about how many pixels to the right each
character should be placed inside the the "character
space". All proportional fonts does not need this array.
If it does not exist the kerning (x offset) will be 0.
2.7.1 TEXTFONT STRUCTURE
The TextFont structure which is declared in header file
"graphics/text.h" is the foundation of all fonts. It consists
of all information which is needed for the system to be able
to print the characters. The structure looks like this:
struct TextFont
{
struct Message tf_Message;
UWORD tf_YSize;
UBYTE tf_Style;
UBYTE tf_Flags;
UWORD tf_XSize;
UWORD tf_Baseline;
UWORD tf_BoldSmear;
UWORD tf_Accessors;
UBYTE tf_LoChar;
UBYTE tf_HiChar;
APTR tf_CharData;
UWORD tf_Modulo;
APTR tf_CharLoc;
APTR tf_CharSpace;
APTR tf_CharKern;
};
tf_Message: The top part of the text font structure consists
of a message are. It is used by the system to
communicate with other parts of the system. If
the font is removed for example, a message is
sent to all involved parts of the system.
The Message structure is defined in header file
"exec/ports.h" as:
struct Message
{
struct Node mn_Node;
struct MsgPort *mn_ReplyPort;
UWORD mn_Length;
};
The Node structure is defined in header file
"exec/nodes.h" as:
struct Node
{
struct Node *ln_Succ;
struct Node *ln_Pred;
UBYTE ln_Type;
BYTE ln_Pri;
char *ln_Name;
};
See chapter 16 "Messages" for more information
about these structures.
If you want to initialize your own TextFont
structure you should set the ln_Succ and ln_Pred
field of the Node structure to NULL. The ln_Type
to "NT_FONT" (font node), the ln_Pri to 0 (normal
priority), and finally the ln_Name to a string
which contains the name of the font.
The mn_ReplyPort pointer of the Message structure
should be set to NULL (Exec will take care of this
later), and the length to the number of bytes is
needed to store the whole font (including this
structure, the name, and the arrays described
below).
tf_YSize: The height of the font (number of pixels/lines).
tf_Style: The style bits as described above:
FS_NORMAL Normal style.
FSF_EXTENDED Extra wide characters.
FSF_ITALIC Italic.
FSF_BOLD Extra thick characters.
FSF_UNDERLINED Underlined characters.
tf_Flags: The font's special flags:
FPF_ROMFONT The font is located in the ROM.
FPF_DISKFONT The font is loaded from a disk.
All fonts you design yourself
must have this flag set unless
you intend to burn your own
memory chips.
FPF_REVPATH The font should be printed in
the opposite direction (right
to left).
FPF_TALLDOT The font is specially designed
for high resolution screens
with no interlace. (Each pixel
is only half as wide as it is
tall.)
FPF_WIDEDOT The font is specially designed
for low resolution screens
which are interlaced. (Each
pixel is only half as tall as
it is wide.)
FPF_PROPORTIONAL The font is proportional. The
width of each character will
vary depending on how wide the
character is itself. The box
containing an "i" will (usually)
not be as wide as a "w" for
example.
FPF_DESIGNED If you have designed the font
for the size specified in
the "tf_ YSize" field this
flag should be set. If a
program has constructed this
size of the font the flag
should not be set. (The
graphical quality of a
Constructed font is usually not
as good as a font which has
been designed for this size.)
FPF_REMOVED This flag is set by the system
when it has been removed.
tf_XSize: The nominal width of each character. If the font
is normal (non proportional) this is the width
between the first pixels of two characters. If a
proportional font is used a special array of
different width for each character may be used.
tf_Baseline: The number of pixels down the baseline is from the
top of the characters. You may not use a base line
which is greater than the nominal height - 1
(tf_YSize-1), or the system may crash!
tf_BoldSmear: When you change the style to bold by calling the
SetSoftStyle() function a copy of the font is
placed on top of itself and a bit to the right.
The further to the right, the bolder characters.
This value represents the number of pixels to the
right the characters should be moved. This value
is usually set to 1, but large fonts usually need
larger values.
tf_Accessors: Several programs may use the same font
simultaneously, and this value represents the
current number of users. Each time the font
is opened by a program this value is increased,
and each time some one closes the font this value
is decreased.
tf_LoChar: A font can consist of up to 256 characters, but
usually the font is much smaller. You can for
example have a font which only consists of
capital letters (A, B, C, .. Y, Z). This field
tells us and the system which is the first
character. In our example the value would be set
to 65 (ASCII 65 = 'A').
tf_HiChar: The last character in this font. In our example
above this value would be set to 90 (ASCII 90 =
'Z').
tf_CharData: Pointer to the character data (the graphics). See
below for more information.
tf_Modulo: The graphics (character data) for the characters
are organized into lines. First comes the top line
of all characters, then the second line and so
on... This value represents the number of bytes
needed for each line.
tf_CharLoc: Pointer to a list of data which tells us where
each character's data begins and how wide each
character is.
tf_CharSpace: Pointer to an array of space information - how
much space is needed between each character when
printed. If this pointer is NULL the nominal
width (tf_XSpace) will be used for all
characters.
tf_CharKern: Pointer to an array of kerning data - how many
pixels to the right the character should be moved
inside its box (character space) when printed. If
the pointer is NULL the kerning (x offset) will
be 0.
2.7.2 FONT (CHARACTER) DATA
The graphics for the characters are organized into an array
of bit packed character data organized into words. Let's say
we want to create our own font of five characters - A, B, C,
D, and E. They should look like this:
**** ***** **** **** ******
** * ** * ** * ** * **
** * ** * ** ** * **
****** ***** ** ** * *****
** * ** * ** ** * **
** * ** * ** * ** * **
** * ***** **** **** ******
Although our font consist of five characters, we must also
define an extra one which will be used when an non existing
character is printed. If we try to print the character G
which does not exist, this special character will be printed.
This character is usually referred as the "not in this font
character". In our example we will use a black box which
looks like this:
********
********
********
********
********
********
********
********
The characters should now be translated into C code. This
is easiest done if you write the characters on a grid paper
and organizes them into groups of four squares. Each group
(binary values) can then easily be translated into hexadecimal
as the following table shows: (Each marked square on your paper
represents the digit '1' and each empty square represents the
digit `0')
Bin Hex
---------
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F
In our example our characters would be translated like this:
-------------------------------------------------------------------------
A B C D E * A B C D E *
-------------------------------------------------------------------------
00111100 01111100 00111100 01111000 01111110 11111111 3C 7C 3C 78 7E FF
01100010 01100010 01100010 01100100 01100000 11111111 62 62 62 64 60 FF
01100010 01100010 01100000 01100010 01100000 11111111 62 62 60 62 60 FF
01111110 01111100 01100000 01100010 01111100 11111111 7E 7C 60 62 7C FF
01100010 01100010 01100000 01100010 01100000 11111111 62 62 60 62 60 FF
01100010 01100010 01100010 01100100 01100000 11111111 62 62 62 64 60 FF
01100010 01111100 00111100 01111000 01111110 11111111 62 7C 3C 78 7E FF
00000000 00000000 00000000 00000000 00000000 11111111 00 00 00 00 00 FF
-------------------------------------------------------------------------
Finally we put the hexadecimal values into an array of words:
/* The font data: */
UWORD MyOwnFontData[24]=
{
0x3C7C,0x3C78,0x7EFF, /* Row 0 */
0x6262,0x6264,0x60FF, /* " 1 */
0x6262,0x6062,0x60FF, /* " 2 */
0x7E7C,0x6062,0x7CFF, /* " 3 */
0x6262,0x6062,0x60FF, /* " 4 */
0x6262,0x6264,0x60FF, /* " 5 */
0x627C,0x3C78,0x7EFF, /* " 6 */
0x0000,0x0000,0x00FF /* " 7 */
};
2.7.3 CHARACTER LOCATION
Secondly we need to tell the computer where each character exist
in the character data, and how wide the character is. In our
example all characters had the same width (8 pixels), but if we
use a proportional font each character may have its own width.
For every character two words are needed. The first word
represents the offset position (the location of the character
in the character data). The second word represents the width
(in bits) of the character.
In our example the character A has the offset value 0 since
it is the first character. The second character (B) has the
offset value 8 since the A was 8 bits wide. The third character
has the offset value 16 (in hexadecimal it is 10) since both A
and B was each 8 bits wide, and so on... All this information
is stored in an array of "longs" (two words).
/* The location and width of each character: */
ULONG MyOwnFontLoc[5]=
{
0x00000008, /* A: Offset 0[hex], Width 8 bits */
0x00080008, /* B: Offset 8[hex], Width 8 bits */
0x00100008, /* C: Offset 10[hex], Width 8 bits */
0x00180008, /* D: Offset 18[hex], Width 8 bits */
0x00200008 /* E: Offset 20[hex], Width 8 bits */
};
2.7.4 CHARACTER SPACE
Normally the default width (tf_XSize) is used as the space
between the first pixel of two character. If the tf_Size is
12, the second character will be printed 12 pixels to the
right and so on... However, if you are using a proportional
font, each character may have its own space. The tf_CharSpace
field should in this case point to an array of words where
each word represents the space of one character. If the
tf_CharSpace field is NULL the nominal width will be used.
(See illustration "Proportional Fonts".)
In our example we used a normal (non proportional) font, and
hence we do not need any array of space information.
2.7.5 CHARACTER KERNING
Some proportional fonts are using "kerning", which is a list
of offset values. These offset values represent the number of
pixels each character will be moved to the right inside its own
character space. The tf_CharKern field must contain the address
of this kerning list of words, or the kerning value 0 will be
used. (See illustration "Proportional Fonts".)
In our example we used a normal (non proportional) font, and
hence we do not need any array of kerning data.
2.7.6 OUR OWN FONT EXAMPLE
In our example the complete C code should look like this:
#include <exec/types.h>
#include <graphics/text.h>
/* The font data: */
UWORD MyOwnFontData[24]=
{
0x3C7C,0x3C78,0x7EFF, /* Row 0 */
0x6262,0x6264,0x60FF, /* " 1 */
0x6262,0x6062,0x60FF, /* " 2 */
0x7E7C,0x6062,0x7CFF, /* " 3 */
0x6262,0x6062,0x60FF, /* " 4 */
0x6262,0x6264,0x60FF, /* " 5 */
0x627C,0x3C78,0x7EFF, /* " 6 */
0x0000,0x0000,0x00FF /* " 7 */
};
/* The location and width of each character: */
ULONG MyOwnFontLoc[5]=
{
0x00000008, /* A: Offset 0[hex], Width 8 bits */
0x00080008, /* B: Offset 8[hex], Width 8 bits */
0x00100008, /* C: Offset 10[hex], Width 8 bits */
0x00180008, /* D: Offset 18[hex], Width 8 bits */
0x00200008 /* E: Offset 20[hex], Width 8 bits */
};
/* The text font structure: */
struct TextFont MyOwnFontFont=
{
{
/* Message */
{
/* Node */
NULL, /* ln_Succ */
NULL, /* ln_Pred */
NT_FONT, /* ln_Type */
0, /* ln_Pri */
"OurFont.font" /* ln_Name */
},
NULL, /* mn_ReplyPort */
72 /* mn_Length */
},
8, /* tf_YSize */
0, /* tf_Style */
66, /* tf_Flags */
8, /* tf_XSize */
6, /* tf_Baseline */
1, /* tf_BoldSmear */
0, /* tf_Accessors */
65, /* tf_LoChar */
69, /* tf_HiChar */
(APTR) &MyOwnFontData, /* tf_CharData */
6, /* tf_Modulo */
(APTR) &MyOwnFontLoc, /* tf_CharLoc */
NULL, /* tf_CharSpace */
NULL, /* tf_CharKern */
};
2.8 FUNCTIONS
OpenFont()
This function is used to get access to a ROM font. You
initialize a TextAttr structure with your requirements,
and send a pointer to it as the only parameter. If
OpenFont() finds the font it returns a pointer to a
TextFont structure and tells the system that you are using
the font. Remember to close all fonts you have opened with
the CloseFont() function.
Synopsis: font = OpenFont( attr );
font: (struct TextFont *) Pointer to a TextFont structure
or NULL if OpenFont() could not find the font.
attr: (struct TextAttr *) Pointer to an initialized
TextAttr structure. OpenFont() will try to open the
font which closes matches your requirements.
CloseFont()
All fonts you have opened with the OpenFont() function must
be "closed" before your program terminates! You close ROM
fonts by calling the CloseFont() function.
Synopsis: CloseFont( font );
font: (struct TextFont *) Pointer to a previously opened
TextFont structure. Note that you should NOT try to
close a font which you have not opened!
AvailFonts()
This function will scan through the font directory of the
system disk, and return a complete list of available fonts.
Note that you must have opened the DiskFont Library before
you may call this function.
Synopsis: missing = AvailFonts( buffer, size, type );
missing: (long) If the buffer was not big enough to store
the complete list of fonts in the extra number of
bytes needed is returned. If 0 is returned the
buffer was big enough for a complete list of fonts.
buffer: (char *) Pointer to some memory were the list of
fonts can be stored.
size: (long) The size of the buffer (in bytes).
type: (long) If you want to look for available fonts
which are already in the memory set the flag
"AFF_MEMORY". If you want to search the disk for
available fonts, set the flag "AFF_DISK". To
search both the memory and the disk set both flags
with the binary OR operator between:
"AFF_DISK | AFF_MEMORY".
OpenDiskFont()
To load fonts from the disk and open them use the
OpenDiskFont() function. Note that you must have opened the
DiskFont Library before you may call this function. Remember
to close all fonts you have opened!
Synopsis: font = OpenDiskFont( attr );
font: (struct TextFont *) Pointer to a TextFont structure
or NULL if OpenFont() could not find the font.
attr: (struct TextAttr *) Pointer to an initialized
TextAttr structure. OpenDiskFont() will try to open
the font which closes matches your requirements.
SetFont()
This function will change a RastPort's font. The font must
of course have been successfully opened before you may start
to use it.
Synopsis: error = SetFont( rp, font );
error: (long) If OK 0 is returned, else an error number is
returned which means something went wrong.
rp: (struct RastPort *) Pointer to the RastPort that
should be affected.
font: (struct TextFont *) Pointer to a TextFont structure
which has previously been "opened".
AskSoftStyle()
This function tells us how a specified font may be changed,
and which styles may be automatically created. Use the
function SetSoftStyle() to later change style. The reason why
you have to check if you are allowed to alter the style is
that some fonts may look very bad when altered.
Note that you should always first try to load the font with
the desired style. It is only when the desired style does not
exist you should try to modify it with the SetSoftStyle()
function.
Synopsis: a_style = AskSoftStyle( rast_port )
a_style: (UWORD) The function returns a bit field where the
allowed style bits for the checked font are set. This
value should be used as a parameter when you later
call the SetSoftStyle() function.
rast_port: (struct RastPort *) Pointer to the rastport to
which the font you want to check is connected.
SetSoftStyle()
This function will alter the style of a specified font. You
should first find out which styles you may alter by calling
the AskSoftStyle() function before you call this function.
Synopsis: new_style = SetSoftStyle( rp, style, a_style );
new_style: (UWORD) The function will only create the styles
it is allowed to do (see a_styles), and it may
therefore happen that the function will not
generate all of the styles you wanted. This
returned value tells us which style bits it used.
rp: (struct RastPort *) Pointer to the rastport to
which the font you want to change is connected.
style: (UWORD) The desired style.
a_style: (UWORD) The styles you may use. This value was
returned by AskSoftStyle(). If you want to be able
to use all styles and do not care if some styles
would look strange set this field to 0xFFFF (all
styles allowed). This can result in some very ugly
styles, and is therefore not recommended.
ClearEOL()
This function will clear the area to the right of the current
position. The height of the area which is cleared is set to
fit the current font height.
Synopsis: ClewarEOL( rp );
rp: (struct RastPort *) Pointer to a rastport. The area
from the current position to the right edge of the
rastport is cleared. The height of the area
depends on the current font size. Normally is the
cleared area set to colour 0, but if you are using
draw mode "JAM2" will the area be filled with the
BgPen colour.
ClearScreen()
This function will clear the area to the right of the current
position and the area below.
Synopsis: ClewarScreen( rp );
rp: (struct RastPort *) Pointer to a rastport. The area
from the current position to the right edge of the
rastport is cleared. The area below is also cleared.
Normally is the cleared area set to colour 0, but
if you are using draw mode "JAM2" will the area be
filled with the BgPen colour.
TextLength()
This function will return the number of pixels wide the text
string would be if printed with the rastport's current font.
Synopsis: width = TextLength( rp, string, nr_chars );
width: (long) Number of pixels wide the text string would
be if printed with the rastport's current font.
rp: (struct RastPort *) Pointer to the rastport.
string: (char *) Pointer to the string containing the text
you want to measure.
nr_chars: (long) Number of characters in the string that
should be counted.
2.9 EXAMPLES
Example 1
This example shows how to open the ROM font "Topaz". (Topaz
is the standard system font, and is placed in ROM on all
Amigas. If you have told preferences to use a 60-character
display the 9 pixel size will be used, else (80-character
display) the 8 pixel size will be used. This example prints
some text in both sizes.
Example 2
This example demonstrates how to change the style of a font.
We will open the ROM font "Topaz" and change the style to
underlined, bold and italic. Well, we try to use all
mentioned styles, but it may happen that we are not allowed
to use some styles.
Example 3
This example demonstrates how to open a disk font (Opal, 12)
and prints some characters with the new font in a window.
Note! The font "Opal" must exist in the systems FONT:
directory or you will receive an error message!
Example 4
This example opens disk fonts and prints some interesting
information about them. (Height, width, flags, style, etc...)
Syntax: Example4 [font1] [font2] [font3] ...
(The largest size of each font will be used.)
Example 5
This example demonstrates how to use the AvailFonts()
function. All available fonts (both on the disk as well as in
the memory) will be listed together with some useful
information about them.
Example 6
This example demonstrates how you can use a font loaded from
a disk in your own Intuition programs.